---
title: 领域建模原理
description: DDD领域建模和传统方法有什么区别？
---

## 什么是领域模型？

在讨论什么是领域模型之前，咱们先说说什么是模型。

先来看几个例子。比如说你去买房，售楼处都会有一个沙盘模型，这样你就可以看到楼的外观、朝向、周边环境等等。

但是如果要盖这个楼盘，靠沙盘模型就不行了，需要有一套详细的建筑图纸，图纸也是模型。为了对大楼进行设计，还要进行各种计算，计算用的公式也是模型，称为数学模型。另外，小孩玩的玩具车、玩具枪什么的，也是模型。事实上，现代生产和生活中，充满着各种各样的模型。


从这些例子里，咱们可以发现模型的几个共同特点。

首先，**模型是以解决特定问题为目的的**。例如沙盘模型是为了卖房，而建筑图纸是为了盖楼。没有目的就谈不上模型。



第二，**模型都是对现实世界或人们思维中的事物进行的模拟**。例如沙盘模型和建筑图纸都是对建筑物的模拟，而玩具车是对真车的模拟。


第三，**模型总是提取了被模拟事物中的部分信息，而忽略掉了其他大部分信息**。例如，沙盘模型提取了楼盘的外观信息，但是忽略了内部结构和建筑材料信息。而建筑图纸反映了内部结构信息，但忽略了外观信息。到底提取哪些信息，忽略哪些信息，取决于模型的目的。


第四，**模型可以有多种表现形式**，例如图纸、影像、公式以及电脑中的文件等等。具体采用哪种形式，取决于要解决的问题和当前的技术水平。

最后，**模型是一种人造物**，大自然本身是不存在模型的。

## 软件开发是一个建模过程
说到这儿，不知道你发现了没有？其实计算机软件也是一种模型。这是因为，计算机软件也是为了满足业务需求，对现实世界的事物和逻辑进行的模拟。所以，我们开发计算机软件的过程也是一个建模过程。

软件本质上是运行在机器上的一串二进制流，我们姑且称之为“机器模型”。我画了一张图，表示了现实世界和机器模型之间的关系。

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201211127.png"/>


我们看到，在机器模型和丰富多彩的现实世界之间存在着巨大的鸿沟，所以，用二进制直接为现实世界建模是非常困难的，这也是软件开发如此困难的原因之一。

那么，如何克服这一障碍呢？打个比方，假如我们想爬到房顶上去，太高了上不去怎么办，那就搬个梯子，一步一步地爬上去。

软件开发的道理是一样的。可以把由现实世界到机器模型的过程分成几步，一步一步地走。传统软件工程中，从现实世界到机器模型的过程，一般是这样的：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201211334.png"/>


**第一步是捕获行为需求**，研究为了满足业务需求需要有怎样的流程和功能，可以用传统的用例分析来做，也可以用咱们这里的事件风暴。

**第二步是分析**，在行为需求的基础上，对现实世界中领域知识或者说业务概念进行分析和提炼，形成分析模型。尽管分析模型反映的仍然是业务概念，然而是经过抽象得来的，更加严谨、精练和一致，因此比行为需求更加接近实现。

**第三步是设计**，在分析模型的基础上，增加技术关注点，进行架构设计、详细设计、数据库设计等，形成设计模型。设计模型介于分析模型和代码之间。

**第四步是编写代码**。代码经过编译后，就成为了运行在机器上的“机器模型”了。

**其实，第二步中的分析，就是对领域知识的抽象和提炼的过程，所以分析模型也可以称为领域模型，这个过程也可以叫做领域建模。**

但是，很多伙伴在开发软件时，并没有经过领域建模这一步，而是直接进行设计和编码。如果是简单系统的话还可以，如果是复杂系统，就会出现很多问题了。

## DDD 领域建模与传统方法的不同之处
既然传统软件工程也有领域模型，那 DDD 的领域模型与传统的方法又有什么不同呢？

这两者之间有一个重要区别：**DDD 强调领域模型要兼顾业务和技术两个视角**。

在传统软件工程里，建立分析模型强调完全从业务领域出发，不考虑技术视角。然后，才会把分析模型交给技术专家，转化为设计模型。两者的关系如下图：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201212244.png"/>

这种方法虽然在理论上是完备的，但实践中常常会有问题。由于在分析阶段没有从技术视角考虑，那么在转化为设计模型的时候，就可能发现有些分析模型很难实现，需要通过复杂的转换，才能适应软件开发的要求，因此两种模型之间就产生了比较大的差距。

所以，在之后的开发过程中，开发人员往往只是聚焦于设计模型，而将分析模型束之高阁。时间久了，分析模型与系统实现之间的差异越来越大，也就失去了存在的意义。最终，技术实现与业务越来越远，软件系统也就难以真实反映业务需求了。

但是，DDD 的领域模型则是 <RedSpan>业务视角（原来的分析模型）和技术视角（原来的设计模型）的交集</RedSpan>。它反映了业务人员和技术人员的共识。

尽管技术人员仍然要为领域模型增加实现细节，形成设计模型，但设计模型必须严格遵循领域模型。对领域模型的修改，必须由业务和技术双方达成一致。这样，就避免了传统软件工程中分析模型和设计模型相互割裂的风险，如下图：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201212353.png"/>

为了表达 DDD 的侧重点，我们把传统的软件开发过程修改为下面这样：

<img src="https://wkq-img.oss-cn-chengdu.aliyuncs.com/20241201212424.png"/>

在这个图中，我们直接用领域建模代替了原来的分析步骤。同时，把原来的设计和编码合并成了模型的实现，这是因为，从敏捷的角度来看，设计和编码常常会融合在一起。


## 模型驱动设计

围绕领域模型进行开发的方法，在 DDD 中称为模型驱动设计（Model-Driven Design），是 DDD 的核心模式之一。这个模式可以概括为两点：

* 领域模型要和业务需求一致。
* 系统实现要和领域模型一致。

### 领域模型要和业务需求一致
首先我们来看看领域模型和业务需求一致。

DDD 非常重视对业务需求中领域知识的消化。虽然我们从事件风暴就开始消化了，但领域建模才是消化知识的核心。在这个过程中，事件风暴里遗留的不清晰的部分会得到解决，并且还会发现新的知识。

事实上，事件风暴和领域建模有一个重要的区别：事件风暴仅仅追求“形似”，也就是说 <RedSpan>业务是怎样运作的，事件风暴就怎样反映</RedSpan>。

而领域模型不仅要和需求“形似”，更要“神似”。也就是说，领域模型不仅要对业务进行直观模拟，更要经过提炼，形成浓缩的知识。


什么意思呢？这里主要是指两点，

<RedSpan>第一点，是通过抽象思维得到更“深刻”的模型</RedSpan>。比如说，我们从企业、开发中心等概念中抽象出组织和组织类别，从人事人员、销售人员中抽象出岗位等等。这使模型中的知识不再停留在业务的表面，而是深入到业务的本质，有利于开发出更加灵活简洁的系统。

<RedSpan>第二点，是通过深入思考得到更“丰富”的模型</RedSpan>。比如说，我们通过分析“取员工上级”的操作，识别出了员工和组织之间关于组织负责人的关联。另外，作为领域知识的一部分，我们还补充了更多的业务规则，这些都使模型更加丰富。蕴含丰富知识的领域模型，可以让我们在开发的时候不容易遗漏重要的领域概念和规则。

另外，领域模型和业务相一致，必须通过业务人员和技术人员的协作才能完成。业务人员的参与，能为领域模型带来专业的领域知识，而技术人员可以为领域模型带来更高的抽象性和严谨性。

而且，技术视角的加入还为领域模型的选择提供了参考。前面我们说过，模型是一种人造物。既然是人造的，就会带入主观因素，对于同一业务，可能会构建出不同形式的领域模型，这些模型可能都“对”，关键在于哪一个“更好”。这时候，技术人员从技术视角出发，往往可以发现，有些模型更容易进行技术实现。所以，尽管领域模型中都是业务概念，却可以通过技术视角选出更恰当的模型。

### 系统实现和领域模型一致
模型驱动设计的第二个要点是系统实现和领域模型一致。

如果修改了领域模型，那么系统实现必然也要修改；反之，如果系统实现发生了变化，也很有可能导致模型的变化。

这背后还隐含了一个推论：<RedSpan>领域模型中的每个元素，都应该通过某种方式在系统实现中有所体现</RedSpan>。反过来说，如果发现领域模型中的某个元素不需要落实到实现里，那么就应该在领域模型里删除这个元素。这也是技术人员参与到领域建模中的一个原因。

根据领域模型进行系统实现的具体技术，我们在会后面的课程中介绍。

领域模型和业务需求一致、系统实现和领域模型一致，最终结果就是系统实现和业务需求总是一致的，避免了系统实现和业务需求差距越来越大，这个老大难问题。

## 领域模型与统一语言

除了<RedSpan>模型驱动设计</RedSpan>以外，DDD 中的另一个核心模式是<RedSpan>统一语言（Ubiquitous Language）</RedSpan>。

统一语言包含了两个层面的含义：一是业务和技术人员之间的语言是统一的，二是开发团队内部各角色之间的语言是统一的。最终结果就是每一行代码都能对应到统一语言，从而与业务保持一致。你可能已经发现了，统一语言和领域模型的目的是一致的。

统一语言的概念其实很容易理解，难点在于怎么真正在实践中贯彻。

要在实践里真正贯彻“统一语言”的理念，我们可以从统一语言的“物质基础”和“实际应用”这两个方面来考虑。领域模型、和词汇表（glossary）和业务规则表等文档性的制品，就是统一语言的“物质基础”。而业务和技术人员在开发过程中的沟通协作，就是统一语言的应用。

这两方面缺一不可。<RedSpan>要用好统一语言，首先要建好领域模型、词汇表和业务规则表</RedSpan>。没有这些，就无法对语言进行规范化和持久化。

另一方面，在所有的协作过程中，每当我们说到领域知识的词汇，都要看一下在领域模型中是否有所反映、大家对同一概念的理解是否一致、已经废弃的词汇是否还在使用等等。

如果发现语言与模型不一致，就要及时纠正，让两者恢复一致。编写代码的时候，也要使代码中的各种命名与模型和词汇表保持一致。在前面的课程里，咱们在建模中模拟了你我两人的对话过程，就是希望你能够体会到语言在沟通中的应用。

如果发现语言与模型不一致，就要及时纠正，让两者恢复一致。编写代码的时候，也要使代码中的各种命名与模型和词汇表保持一致。在前面的课程里，咱们在建模中模拟了你我两人的对话过程，就是希望你能够体会到语言在沟通中的应用。

## 总结
软件开发也是一个建模过程。为了跨越现实世界和机器模型之间的鸿沟，人们采用了“分步走”的方式。其中，在传统软件工程中的分析步骤产生的分析模型，也叫做领域模型。


但是，DDD 的领域模型与传统软件工程有一个重要的区别，就是，<RedSpan>DDD 强调领域模型要兼顾业务和技术两个视角</RedSpan>，而不像传统方法那样，只关注业务视角。


所以，我们可以说：DDD 的领域模型是为了满足业务需求，对领域知识进行提炼和抽象的产物，反映了业务和技术人员的共同视角。一方面，它能够全面和深刻地反映领域知识，另一方面又能方便地转化为技术实现。


DDD 的核心模式之一：<RedSpan>模型驱动设计就是围绕领域模型展开的</RedSpan>。它有两个要点：领域模型和业务需求要保持一致；系统实现和领域模型也要保持一致。最终的结果就是系统实现和业务需求保持一致。


除此之外，DDD 还有另一个核心模式：<RedSpan>统一语言</RedSpan>。要用好统一语言，一方面要建立好领域模型、词汇表等“物质基础”，另一方面要在沟通协作的过程中，不断保持模型、语言和系统实现的一致性。